import { useCallback, useReducer } from "react";

const UNDO = "undo";
const REDO = "redo";
const SET = "set";
const RESET = "reset";

interface StateType<T> {
  past: T[];
  present: T;
  future: T[];
}

interface ActionType<T> {
  newPresent?: T;
  type: typeof UNDO | typeof REDO | typeof SET | typeof RESET;
}

const undoReducer = <T>(
  state: StateType<T>,
  { type, newPresent }: ActionType<T>
) => {
  const { present, past, future } = state;
  switch (type) {
    case UNDO:
      if (!past.length) return state;

      return {
        past: past.slice(0, past.length - 1),
        present: past[past.length - 1],
        future: [present, ...future],
      };

    case REDO:
      if (!future.length) return state;

      return {
        past: [...past, present],
        present: future[0],
        future: future.splice(1),
      };

    case SET:
      if (newPresent === present) return state;

      return {
        past: [...past, present],
        present: newPresent,
        future: [],
      };

    case RESET:
      return {
        past: [],
        present: newPresent,
        future: [],
      };

    default:
      return state;
  }
};

export const useUndo = <T>(initialPresent: T) => {
  const [state, dispatch] = useReducer(undoReducer, {
    past: [],
    present: initialPresent,
    future: [],
  } as StateType<T>);

  console.log(state, "state");

  const canUndo = !!state.past.length;
  const canRedo = !!state.future.length;

  const undo = useCallback(() => {
    dispatch({ type: UNDO });
  }, []);

  const redo = useCallback(() => {
    dispatch({ type: REDO });
  }, []);

  const set = useCallback((newPresent: T) => {
    dispatch({ type: SET, newPresent });
  }, []);

  const rest = useCallback((newPresent: T) => {
    dispatch({ type: RESET, newPresent });
  }, []);

  return [state, { set, rest, undo, redo, canRedo, canUndo }] as const;
};
